package com.hengpeng.itfin.job.mail.support;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hengpeng.itfinbase.persist.EmailLog;

/**
 * <pre>
 * 邮件发送器 MailSender.getInstance().send(email);
 * </pre>
 * @author shanguogang
 * @version 1.0, 2015-07-31
 */
public class MailSender
{
	private final static int POOL_SIZE = 4;

	private volatile static MailSender instance;

	private final static BlockingQueue<EmailLog> queue = new LinkedBlockingQueue<EmailLog>();

	private static boolean isStop = true;

	private static final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
			.availableProcessors() * POOL_SIZE);

	private static final Log log = LogFactory.getLog(MailSender.class);

	public static MailSender getInstance()
	{
		if (instance == null)
		{
			synchronized (MailSender.class)
			{
				if (instance == null)
				{
					instance = new MailSender();
				}
			}
		}
		return instance;
	}

	public static boolean isStop()
	{
		return isStop;
	}

	/** 关闭线程池 启动一次顺序关闭，执行以前提交的任务，但不接受新任务 */
	public synchronized void shutdown()
	{
		executorService.shutdown();
		isStop = true;
		notifyAll();
	}

	/**
	 * <pre>
	 * 添加新的邮件到发送队列
	 * </pre>
	 * @param email
	 */
	public synchronized void send(EmailLog email)
	{
		if (isStop)
		{
			throw new IllegalStateException("邮件发送线程已关闭...");
		}
		try
		{
			queue.put(email);
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		notifyAll();
	}

	/** 从工作队列中取出一个任务，工作线程会调用此方法 */
	public synchronized Runnable getTask() throws InterruptedException
	{
		while (queue.size() == 0)
		{
			if (isStop)
				return null;// 等待前检查线程池是否关闭
			wait();
			if (isStop)
				return null;// 等待后再次检查线程池是否关闭
		}
		return new EmailHandler(queue.poll());

	}

	public void start()
	{
		if (!isStop)
		{
			log.info("邮件线程已开启,若想重新开启,请先闭关当前线程");
			return;
		}
		isStop = false;
		log.info("邮件发送线程已启动");
		while (true)
		{
			try
			{
				Runnable r = getTask();
				if (!isStop)
					executorService.execute(r);
				else
					break;
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}
}
